const jwt = require("jsonwebtoken");

// 定义 token 相关 error
const ErrTokenExpired = new Error("token 已过期, 请重新登录");
const ErrTokenNotValidYet = new Error("token 无效, 请重新登录");
const ErrTokenMalformed = new Error("token 不正确, 请重新登录");
const ErrTokenInvalid = new Error("这不是一个 token, 请重新登录");

class MyClaims {
  constructor(userId, role, uuid, iss, exp) {
    this.userId = userId;
    this.role = role;
    this.uuid = uuid;
    this.iss = iss;
    this.exp = exp;
  }
}
class MyJWT {
  constructor(secret) {
    this.secret = secret;
  }
  genToken(userId, role, uuid) {
    let claims = new MyClaims(
      userId,
      role,
      uuid,
      "gin-vue-blog",
      "Math.floor(Date.now() / 1000) + 24 * 60 * 60"
    );
    /* 
      algorithm指定加密算法
        Secret = "abc123321"
        Expire = 24             # 过期时间 (小时)
        Issuer = "gin-vue-blog" 这里设置为vue，重构项目尽量保持一致
      */
    //属于加密前的原始数据
    const claimsObject = {
      userId: claims.userId,
      role: claims.role,
      uuid: claims.uuid,
    };

    //要求是纯对象
    const token = jwt.sign(claimsObject, this.secret, {
      issuer: "gin-vue-blog",
      expiresIn: "24h",
      algorithm: "HS256",
    });
    return token;
  }
  parseToken(tokenString) {
    try {
      let decoded = jwt.verify(tokenString, this.secret);

      //将解密的数据实例化一下返回
      return new MyClaims(
        decoded.userId,
        decoded.role,
        decoded.uuid,
        decoded.iss,
        decoded.exp
      );
    } catch (error) {
      if (err instanceof jwt.TokenExpiredError) {
        //过期
        throw ErrTokenExpired;
      } else if (err instanceof jwt.JsonWebTokenError) {
        if (err.message === "jwt malformed") {
          //token不正确
          throw ErrTokenMalformed;
        } else if (err.message === "jwt not active") {
          //token无效
          throw ErrTokenNotValidYet;
        }
      }
      //都不是加密处理过的token
      throw ErrTokenInvalid;
    }
  }
}

const myJWT = new MyJWT("abc123321");

module.exports = myJWT;
